package com.sky.interceptor;

import com.alibaba.fastjson.JSON;
import com.sky.properties.JwtProperties;
import com.sky.result.Result;
import com.sky.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.entity.ContentType;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 *  ThreadLocal已经在过滤器里面做过了，此处不做     此处使用拦截器只是为了方便学习
 *
 *  拦截器 TODO 未生效的拦截器  -- 已处理
 *  需要拦截的资源需要在 SpringMvcConfig.java 中配置
 */
@Slf4j
//@Component
public class GlobalInterceptor implements HandlerInterceptor {

    private RedisTemplate redisTemplate;

    public GlobalInterceptor(RedisTemplate redisTemplate){
        this.redisTemplate = redisTemplate;
    }



    // mvc路径匹配器
    private static final AntPathMatcher PATH_MATCHER = new AntPathMatcher();

    //需要放行的资源路径  Swagger、登录接口、登出接口
    String[] urls = {"/swagger-ui.html","/webjars/**","/swagger-resources/**","/swagger-resources","/v2/**","/csrf",
                     "/admin/employee/login","/admin/employee/logout",
                     "/ws/**", "/admin/websocket/paySuccessOrder", "/admin/websocket/reminder"};

    //注入工具实体bean
    @Resource
    private JwtProperties jwtProperties;


    //方法执行前执行
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //System.out.println("GlobalInterceptor - 当前线程id：" + Thread.currentThread().getId());
        //System.out.println(ContentType.APPLICATION_JSON.toString());
        //System.out.println(jwtProperties);
        response.setContentType(ContentType.APPLICATION_JSON.toString());


        // 1. 获取当前请求路径
        String requestURI = request.getRequestURI();
        log.info("GlobalInterceptor - 当前请求url: {}", requestURI);

        // 2.校验当前路径是否是需要放行
        Boolean flag = checkUrl(urls, requestURI);

        // 3.判断校验结果
        if(flag){
            log.info("拦截器,当前路径:{} 放行", requestURI);
            //放行并结束方法
            return true;
        }

        // 4.不是放行路径，则校验  获取token
        String jwtToken = request.getHeader(jwtProperties.getAdminTokenName());

        // 5.判断token是否处在
        if( !StringUtils.hasLength(jwtToken) ){
            log.info("拦截器-当前资源路径：{} 需要校验，但token为空，请先登录", requestURI);
            //封装token错误信息 返回
            Result<Object> error = Result.error("拦截器-token为空，请先登录");
            response.getWriter().println(JSON.toJSONString(error));
            //不放行 且 结束方法
            return false;
        }

        // 6.去除token前缀 "Bearer "
        String token = jwtToken.replace("Bearer ", "");

        // 7.解析token
        try {
            Claims claims = JwtUtil.parseJWT(jwtProperties.getAdminSecretKey(), token);
        } catch (Exception e) {
            log.info(requestURI + " -- 拦截器-token令牌解析异常");
            //封装token解析错误信息 并 写回
            Result<Object> error = Result.error("拦截器-token解析异常，请重新登录");
            response.getWriter().println(JSON.toJSONString(error));
            //不放行 且 结束方法
            return false;
        }

        //已登录，拦截器放行
        log.info("GlobalInterceptor - " + requestURI + " - 令牌合法，放行");
        return true;
    }

    //路径匹配
    private Boolean checkUrl(String[] urls, String requestURI) {
        for (String url : urls) {
            boolean flag = PATH_MATCHER.match(url, requestURI);
            if(flag){
                return true;
            }
        }
        return false;

    }


    //方法执行后执行
    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("GlobalInterceptor - postHandle() ......");
    }


    //视图渲染完毕后执行，最后执行
    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("GlobalInterceptor - afterCompletion() ......");
    }
}
